/*
 *      IP.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#ifndef _IP_IMPL
#define _IP_IMPL

#include "IP.h"
/**\brief Funzione di immissione nella struttura di indicizzazione delgli indirizzi ip di un nuovo alert.
 * 
 * Dopo aver estratto dal nodo XML da inserire gli indirizzi ip, li pone nelle strutture di indicizzazione
 * immediatamente dopo il nodo con l'indirizzo ip minore e più vicino a quello da inserire
 * \param AlertList *root Puntatore alla posizione in cui andrà inserito l'alert
 * \param xmlNode *father Puntatore al nodo XML contenente l'alert
 */
#ifdef _WIN32 
static void setAddress(AlertList *root, xmlNode *father){
#else
void setAddress(AlertList *root, xmlNode *father){
#endif
	xmlNode *son;
	//~ iIp *src;
	iIp *trg;
	//~ iIp *src;
	unsigned char ip1,ip2,ip3,ip4;
	unsigned int i1,i2,i3,i4;
	long int ip;														// Intero costruito con i 3 LSByte dell'ip
	indexIpList *newitem;
	
	for(son = father->CHILDREN; son; son = son->NEXT){
		if((strncmp((char *)son->name,"address",8)==0)&&(son->children!=NULL)){
			if(son->CONTENT!=NULL){
				sscanf((char *)son->CONTENT,"%d.%d.%d.%d",&i1,&i2,&i3,&i4);
				ip1=i1;
				ip2=i2;
				ip3=i3;
				ip4=i4;
				ip=256*256*ip2+256*ip3+ip4;
				trg=lastIpAddr(&indexIp[i1],ip,(char)son->parent->parent->parent->name[0]+('a'-'A'));
				trg->ip=ip;
				trg->ip1=ip1;
				trg->ip2=ip2;
				trg->ip3=ip3;
				trg->ip4=ip4;
				trg->referred=root;
				newitem=(indexIpList *)malloc(sizeof(indexIpList));
				newitem->item=trg;
				newitem->next=root->ip_index;
				root->ip_index=newitem;			
			}
		}
		if((strncmp((char *)son->name,"netmask",8)==0)&&(son->children!=NULL)){
			if(son->CONTENT!=NULL){
				//insert into index struct
			}
		}

	}
}
/**\brief Ricerca la posizione di inserimento del nuovo alert nella struttura di indicizzazione.
 * 
 * Nella struttura di indicizzazione viene effettuata la ricerca della posizione di inserimento del nuovo alert:
 * si scorre la lista degli indirizzi fino a trovarne uno superiore a quello da inserire o fino alla fine e si cre il
 * nuovo nodo oppure, in caso di lista vuota, viene creato un nuovo nodo all'inizio della lista.
 * \param IndexIp *top Puntatore alla lista di indirizzi
 * \param long int ip Somma degli ultimi tre byte dell'indirizzo ip dell'alert da inserire
 * \param char type Tipo di indirizzo (Source o Target)
 * \return iIp * Puntatore al nodo in cui inserire l'alert
 */
#ifdef _WIN32 
static iIp *lastIpAddr(IndexIp *top, long int ip,char type){
#else
iIp *lastIpAddr(IndexIp *top, long int ip,char type){
#endif
	iIp *cur,*old;
	
	if(type=='s'){
		cur=top->sourceItem;
	}else if(type=='t'){
		cur=top->targetItem;
	}
	if(cur == NULL){
		cur=HeadIns(top,cur,type);
	}else{	
		old=cur;
		while((cur->down != NULL) && (cur->ip<ip)){
			old=cur;		
			cur=cur->down;
		}
		if(cur->down==NULL){
			if(cur->ip>ip){
				if(old==cur){
					cur=HeadIns(top,cur,type);
				}else{
					cur=BetweenIns(top,old,cur,type);
				}
			}else{
				cur=BottomIns(top,cur,type);
			}
		}else{
			if(old==cur){
				cur=HeadIns(top,cur,type);
			}else{
				cur=BetweenIns(top,old,cur,type);
			}
		}
	}
	return cur;
}
/**\brief Funzione di parsing delle query relative agli indirizzi ip
 *
 * Questa funzione viene richiamata da pTree_newnode per effettuare il parsing della sezione where delle query relative
 * agli indirizzi ip.<br>
 * Nella fase di inizializzazione occorre inserire il puntatore a questa funzione nell'elemento della lista relativo
 * agli indirizzi ip.<br>
 * \param this Nodo dell'albero di esecuzione che contiene l'istruzione di filtraggio sugli indirizzi ip
 * \param where Stringa contenente la sezione where della query
 * \param index Indice dell'inizio della porzione della stringa \awhere relativo al filtro sugli indirizzi ip
 * \param i Indice di lettura della stringa \awhere
 */
#ifdef _WIN32 
static int parse_ip(processingTree *this,char *where,int index,int *i){
#else
int parse_ip(processingTree *this,char *where,int index,int *i){
#endif
	int ip1,ip2,ip3,ip4,ip1_2,ip2_2,ip3_2,ip4_2;
	char *operation;
	char t=0;
	bool btw=false;


	while((where[*i]!=' ') && (where[*i]!=')') && (where[*i]!=WHERE_T)){
		*i=*i+1;
	}
	if((operation=(char *)calloc(sizeof(char),*i-index+1))==NULL){
		return -451;
	}
	strncpy(operation,&where[index],*i-index);
	if(operation[3]=='='){
		if(sscanf(operation,"IP%c=%d.%d.%d.%d",&t,&ip1,&ip2,&ip3,&ip4)<=0){
			free(operation);
			return -501;
		}
	}else if(operation[3]=='!'){
		if(sscanf(operation,"IP%c!=%d.%d.%d.%d",&t,&ip1,&ip2,&ip3,&ip4)<=0){
			free(operation);
			return -501;
		}
	}else if(operation[3]=='_'){
		btw=true;
		if(operation[7]=='='){
			if(sscanf(operation,"IP%c_BTW=%d.%d.%d.%d|%d.%d.%d.%d",&t,&ip1,&ip2,&ip3,&ip4,&ip1_2,&ip2_2,&ip3_2,&ip4_2)<=0){
				free(operation);
				return -501;
			}
		}else if(operation[7]=='!'){
			if(sscanf(operation,"IP%c_BTW!=%d.%d.%d.%d|%d.%d.%d.%d",&t,&ip1,&ip2,&ip3,&ip4,&ip1_2,&ip2_2,&ip3_2,&ip4_2)<=0){
				free(operation);
				return -501;
			}
		}
	}else{
		free(operation);
		return -501;
	}
	if(t=='s'||t=='t'||t=='h'){
		if(((ip1>0)&&(ip1<256))&&((ip2>=0)&&(ip2<256))&&((ip3>=0)&&(ip3<256))&&((ip4>=0)&&(ip4<256))){
			if(btw==true){
				if(!(((ip1_2>0)&&(ip1_2<256))&&((ip2_2>=0)&&(ip2_2<256))&&((ip3_2>=0)&&(ip3_2<256))&&((ip4_2>=0)&&(ip4_2<256)))){
					free(operation);
					return -501;
				}
			}
			this->OP=(char *)calloc(sizeof(char),*i-index+1);
			strncpy(this->OP,operation,*i-index);
			free(operation);
			while(where[*i]==' '){
				*i=*i+1;
			}
			if(where[*i]!=WHERE_T){
				this->nextbro=(processingTree *)malloc(sizeof(processingTree));
				setBro(this);
				*i=pTree_newnode(this->nextbro,where,*i,NEW_BRO);
			}
			return *i;
		}
	}
	free(operation);
	return -501;
}
/**\brief Cancellazione dei nodi dalla struttura di indicizzazione degli indirizzi ip
 *
 * Questa funzione si occupa della rimozione dei nodi relativi a un dato alert dalla struttura di indicizzazione
 * degli indirizzi ip.
 * \param to_delete Puntatore all'alert da rimuovere
 */
#ifdef _WIN32 
static void del_ip_index(AlertList *to_delete){
#else
void del_ip_index(AlertList *to_delete){
#endif
	indexIpList *old_index,*ip_delete;
	IndexIp *ip_top_point;
	
	if(to_delete->ip_index!=NULL){
		ip_delete=to_delete->ip_index;
		while(ip_delete){
			old_index=ip_delete;
			ip_delete=ip_delete->next;
			if(old_index->item->prev!=old_index->item){
				old_index->item->prev->down=old_index->item->down;
				if(old_index->item->down!=NULL){
					old_index->item->down->prev=old_index->item->prev;
				}
			}else{
				ip_top_point=(IndexIp *)old_index->item->top;
				if(old_index->item->down!=NULL){
					old_index->item->down->prev=old_index->item->down;
				}
				if(old_index->item->type=='s'){
					ip_top_point->sourceItem=old_index->item->down;
				}else if(old_index->item->type=='t'){
					ip_top_point->targetItem=old_index->item->down;
				}
			}
			free(old_index->item);
			free(old_index);
		}
	}
}
/**\brief Esegue una prima scrematura determinando che tipo di filtro occorre usare
 *
 * In base alla stringa di identificazione presente nel nodo del processingTree che viene passato come parametro si
 * determina quale tipo di filtro eseguire.
 * \param processingTree *this Puntatore al nodo dell'albero di esecuzione che determina l'operazione da eseguire
 * \param stringList *sel Puntatore alla lista delle stringhe delle sezione select che determinano quali campi inviare
 * \param VortexConnection *cn Connessione sulla quale inviare i risultati
 * \param VortexChannell *ch Canale sul quale inviare i risultati
 * \return xmlNodeList * Puntatore alla lista dei risultati
 */
#ifdef _WIN32 
static xmlNodeList *ip_filters(processingTree *this,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *ip_filters(processingTree *this,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	xmlNodeList *lista=NULL,*listb=NULL;
	
	if(strncasecmp(this->OP,"IPh=",4)==0){
		//dove host è definito come IPs OR IPt
		//quindi host!= per DeMorgan diventa !(IPs OR IPt)=!IPs AND !IPt
		lista=IPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[4],'s',NULL,NULL,NULL);
		listb=IPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[4],'t',NULL,NULL,NULL);
		return (this->father==this)?or(this->sign_mode,this->sign_num,this->step_num,lista,listb,sel,cn,ch):or(this->sign_mode,this->sign_num,this->step_num,lista,listb,NULL,NULL,NULL);
	}
	if(strncasecmp(this->OP,"IPh_BTW=",8)==0){	
		lista=betweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[8],'s',NULL,NULL,NULL);
		listb=betweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[8],'t',NULL,NULL,NULL);
		return (this->father==this)?or(this->sign_mode,this->sign_num,this->step_num,lista,listb,sel,cn,ch):or(this->sign_mode,this->sign_num,this->step_num,lista,listb,NULL,NULL,NULL);
	}
	if(strncasecmp(this->OP,"IPh!=",5)==0){
		lista=notIPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[5],'s',NULL,NULL,NULL);
		listb=notIPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[5],'t',NULL,NULL,NULL);
		return (this->father==this)?join(this->sign_mode,this->sign_num,this->step_num,lista,listb,sel,cn,ch):join(this->sign_mode,this->sign_num,this->step_num,lista,listb,NULL,NULL,NULL);
	}
	if(strncasecmp(this->OP,"IPh_BTW!=",9)==0){	
		lista=notbetweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[9],'s',NULL,NULL,NULL);
		listb=notbetweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[9],'t',NULL,NULL,NULL);
		return (this->father==this)?join(this->sign_mode,this->sign_num,this->step_num,lista,listb,sel,cn,ch):join(this->sign_mode,this->sign_num,this->step_num,lista,listb,NULL,NULL,NULL);
	}
	if((strncasecmp(this->OP,"IPs=",4)==0) || (strncasecmp(this->OP,"IPt=",4)==0)){
		return (this->father==this)?IPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[4],this->OP[2],sel,cn,ch):IPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[4],this->OP[2],NULL,NULL,NULL);
	}
	if((strncasecmp(this->OP,"IPs!=",5)==0) || (strncasecmp(this->OP,"IPt!=",5)==0)){
		return (this->father==this)?notIPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[5],this->OP[2],sel,cn,ch):notIPfilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[5],this->OP[2],NULL,NULL,NULL);
	}
	if((strncasecmp(this->OP,"IPs_BTW=",8)==0) || (strncasecmp(this->OP,"IPt_BTW=",8)==0)){
		return (this->father==this)?betweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[8],this->OP[2],sel,cn,ch):betweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[8],this->OP[2],NULL,NULL,NULL);
	}
	if((strncasecmp(this->OP,"IPs_BTW!=",9)==0) || (strncasecmp(this->OP,"IPt_BTW!=",9)==0)){
		return (this->father==this)?notbetweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[9],this->OP[2],sel,cn,ch):notbetweenIP(this->sign_mode,this->sign_num,this->step_num,&this->OP[9],this->OP[2],NULL,NULL,NULL);
	}
	return NULL;	
}
/**\brief Filtro sull'indirizzo ip
 *
 * Effettua la ricerca in base all'indirizzo ip che viene passato, restituendo una lista ordinata di tutti gli alert
 * in cui l'indirizzo corrisponde a quello passato come parametro.
 * \param char *ip L'indirizzo ip da utilizzare come rifericìmento nella ricerca
 * \param char type Indica il tipo di indirizzo (Source o Target)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *IPfilter(unsigned char sign_mode,int sign_num,int step_num,char *ip,char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *IPfilter(unsigned char sign_mode,int sign_num,int step_num,char *ip,char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	int cnt=0;
	iIp *cur;
	xmlNodeList *pos;
	long int xip;
	int ip1,ip2,ip3,ip4;
	AlertList *local;
	
	sscanf(ip,"%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
	xip=256*256*ip2+256*ip3+ip4;
	
	pos=NULL;
	pos=newxmlNodeList();
	if(type=='s'){
		cur = indexIp[ip1].sourceItem;
	}else if(type=='t'){
		cur = indexIp[ip1].targetItem;
	}
	while(cur != NULL){
		local=cur->referred;
		if((cur->ip==xip) && ((local->match[sign_num]&pow2[step_num])==0)^sign_mode){
			if(sel==NULL){
				setNodePointer(pos,cur->referred);
				cnt++;
			}else{
				visualMessage(sign_num,step_num,cur->referred,sel,cn,ch);
			}
		}
		cur=cur->down;	
	}
	return (cnt>0)? pos : freexmlNodeList(pos);
}

/**\brief Filtro negato sull'indirizzo ip
 *
 * Effettua la ricerca in base all'indirizzo ip che viene passato, restituendo una lista ordinata di tutti gli alert
 * in cui l'indirizzo non corrisponde a quello passato come parametro.
 * \param char *ip L'indirizzo ip da utilizzare come rifericìmento nella ricerca
 * \param char type Indica il tipo di indirizzo (Source o Target)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *notIPfilter(unsigned char sign_mode,int sign_num,int step_num,char *ip,char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *notIPfilter(unsigned char sign_mode,int sign_num,int step_num,char *ip,char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	int cnt=0,i=0;
	iIp *cur;
	xmlNodeList *pos;
	long int xip;
	int ip1,ip2,ip3,ip4;
	AlertList *local;
	
	sscanf(ip,"%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
	xip=256*256*ip2+256*ip3+ip4;

	pos=NULL;
	pos=newxmlNodeList();
	for(i=0;i<256;i++){
		if(type=='s'){
			cur = indexIp[i].sourceItem;
		}else if(type=='t'){
			cur = indexIp[i].targetItem;
		}
		while(cur!=NULL){
			local=cur->referred;
			if(((cur->ip1!=ip1) || (cur->ip!=xip)) && ((local->match[sign_num]&pow2[step_num])==0)^sign_mode){
				if(sel==NULL){
					setNodePointer(pos,cur->referred);
					cnt++;
				}else{
					visualMessage(sign_num,step_num,cur->referred,sel,cn,ch);
				}
			}
			cur=cur->down;
		}
	}
	
	return (cnt>0)? pos : freexmlNodeList(pos);
}

/**\brief Filtro un intervallo di indirizzi ip
 *
 * Effettua la ricerca in base agli indirizzo ip che vengono passati, restituendo una lista ordinata di tutti gli
 * alert in cui l'indirizzo è compreso tra di essi
 * \param char *ip I due indirizzi ip da utilizzare come rifericìmento nella ricerca nel formato<br>
 * ip1.ip2.ip3.ip4|ip1.ip2.ip3.ip4
 * \param char type Indica il tipo di indirizzo (Source o Target)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *betweenIP(unsigned char sign_mode,int sign_num,int step_num,char *ip, char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *betweenIP(unsigned char sign_mode,int sign_num,int step_num,char *ip, char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	long int LowIP,HighIP,lbox;
	int Lip1,Hip1,ipl2,ipl3,ipl4,iph2,iph3,iph4,box,tot=0,i;
	iIp *cur_src;
	xmlNodeList *dst;
	AlertList *local;

	dst=NULL;
	dst=newxmlNodeList();
	sscanf(ip,"%d.%d.%d.%d|%d.%d.%d.%d",&Lip1,&ipl2,&ipl3,&ipl4,&Hip1,&iph2,&iph3,&iph4);
	LowIP=256*256*ipl2+256*ipl3+ipl4;
	HighIP=256*256*iph2+256*iph3+iph4;
	
	if(Hip1<Lip1){
		box=Lip1;lbox=LowIP;Lip1=Hip1;LowIP=HighIP;Hip1=box;HighIP=lbox;
	}else if(Hip1==Lip1){
		if(HighIP<LowIP){
			box=Lip1;lbox=LowIP;Lip1=Hip1;LowIP=HighIP;Hip1=box;HighIP=lbox;
		}	
	}
	for(i=Lip1;i<=Hip1;i++){
		if(type=='s'){
			cur_src=indexIp[i].sourceItem;
		}else if(type=='t'){
			cur_src=indexIp[i].targetItem;
		}
		while(cur_src!=NULL){
			local=cur_src->referred;
			if(((local->match[sign_num]&pow2[step_num])==0)^sign_mode &&(((cur_src->ip1>Lip1)&&(cur_src->ip1<Hip1))||((cur_src->ip1==Lip1)&&(cur_src->ip>=LowIP))||((cur_src->ip1==Hip1)&&(cur_src->ip<=HighIP)))){
				if(sel==NULL){
					setNodePointer(dst,cur_src->referred);
					tot++;
				}else{
					visualMessage(sign_num,step_num,cur_src->referred,sel,cn,ch);
				}
			}
			cur_src=cur_src->down;
		}
	}
	return (tot>0)? dst : freexmlNodeList(dst);
}

/**\brief Filtro un intervallo di indirizzi ip negato
 *
 * Effettua la ricerca in base agli indirizzo ip che vengono passati, restituendo una lista ordinata di tutti gli
 * alert in cui l'indirizzo non è compreso tra di essi
 * \param char *ip I due indirizzi ip da utilizzare come rifericìmento nella ricerca nel formato<br>
 * ip1.ip2.ip3.ip4|ip1.ip2.ip3.ip4
 * \param char type Indica il tipo di indirizzo (Source o Target)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *notbetweenIP(unsigned char sign_mode,int sign_num,int step_num,char *ip, char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){ 
#else
xmlNodeList *notbetweenIP(unsigned char sign_mode,int sign_num,int step_num,char *ip, char type,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	long int LowIP,HighIP,lbox;
	int Lip1,Hip1,ipl2,ipl3,ipl4,iph2,iph3,iph4,box,tot=0,i;
	iIp *cur_src;
	xmlNodeList *dst;
	AlertList *local;
	
	dst=NULL;
	dst=newxmlNodeList();
	sscanf(ip,"%d.%d.%d.%d|%d.%d.%d.%d",&Lip1,&ipl2,&ipl3,&ipl4,&Hip1,&iph2,&iph3,&iph4);
	LowIP=256*256*ipl2+256*ipl3+ipl4;
	HighIP=256*256*iph2+256*iph3+iph4;
	
	if(Hip1<Lip1){
		box=Lip1;lbox=LowIP;Lip1=Hip1;LowIP=HighIP;Hip1=box;HighIP=lbox;
	}else if(Hip1==Lip1){
		if(HighIP<LowIP){
			box=Lip1;lbox=LowIP;Lip1=Hip1;LowIP=HighIP;Hip1=box;HighIP=lbox;
		}	
	}
	for(i=0;i<256;i++){
		if(type=='s'){
			cur_src=indexIp[i].sourceItem;
		}else if(type=='t'){
			cur_src=indexIp[i].targetItem;
		}
		while(cur_src!=NULL){
			local=cur_src->referred;
			if(((local->match[sign_num]&pow2[step_num])==0)^sign_mode && (((cur_src->ip1<Lip1)||(cur_src->ip1>Hip1))||((cur_src->ip1==Lip1)&&(cur_src->ip<LowIP))||((cur_src->ip1==Hip1)&&(cur_src->ip>HighIP)))){
				if(sel==NULL){
					setNodePointer(dst,cur_src->referred);
					tot++;
				}else{
					visualMessage(sign_num,step_num,cur_src->referred,sel,cn,ch);
				}
			}
			cur_src=cur_src->down;
		}
	}
	return (tot>0)? dst : freexmlNodeList(dst);
}

#endif
